using System.Drawing;
using JetBrains.Annotations;
using JetBrains.CommonControls;
using JetBrains.ProjectModel;
using JetBrains.ReSharper.Feature.Services.Generate;
using JetBrains.ReSharper.Psi;
using JetBrains.ReSharper.Psi.Xaml.Impl.DeclaredElements;
using JetBrains.Text;
using JetBrains.TreeModels;
using JetBrains.UI.RichText;
using JetBrains.UI.TreeView;

namespace GammaJul.ReSharper.GammaXaml.Services.CSharp.Generate {

	/// <summary>
	/// Encapsules a <see cref="IField"/> for dependency property generation.
	/// </summary>
	internal sealed class DpGeneratorField : GeneratorDeclaredElement, IGeneratorElementPresenter {
		private readonly IType _dpRegisteredType;
		private readonly bool _isAttached;

		private sealed class DpGroup {

			internal static readonly DpGroup Properties = new DpGroup();
			internal static readonly DpGroup AttachedProperties = new DpGroup();

			private DpGroup() {
			}
		}


		/// <summary>
		/// Gets the dependency property field.
		/// </summary>
		[NotNull]
		public new IField DeclaredElement {
			get { return (IField) base.DeclaredElement; }
		}

		/// <summary>
		/// Gets the registered type of <see cref="DeclaredElement"/>.
		/// </summary>
		[NotNull]
		public IType DpRegisteredType {
			get { return _dpRegisteredType; }
		}

		/// <summary>
		/// Gets whether the field represents an attached dependency property.
		/// </summary>
		public bool IsAttached {
			get { return _isAttached; }
		}

		public override object GetPresentationObject() {
			return DeclaredElement;
		}

		public override object GetGroupingObject() {
			return new CascadeGroup(new[] { _isAttached ? DpGroup.AttachedProperties : DpGroup.Properties, base.GetGroupingObject() });
		}

		public override bool Matches(string searchText, IdentifierMatcher matcher) {
			return matcher.Matches(DeclaredElement.ShortName);
		}

		public override string TestDescriptor {
			get { return GetTestDescriptor(DeclaredElement, DeclaredElement.IdSubstitution); }
		}

		public void InitGeneratorPresenter(StructuredPresenter<TreeModelNode, IPresentableItem> presenter) {
			presenter.Present<DpGroup>(PresentDpGroup);
		}

		private void PresentDpGroup(DpGroup value, IPresentableItem item, TreeModelNode structureElement, PresentationState state) {
			var psiIconManager = DeclaredElement.GetSolution().GetComponent<PsiIconManager>();
			if (value == DpGroup.Properties) {
				item.RichText = new RichText("Dependency Properties", new TextStyle(FontStyle.Italic));
				item.Images.Add(psiIconManager.GetImage(CLRDeclaredElementType.PROPERTY, PsiIconExtension.ReadWriteAccess));
			}
			else if (value == DpGroup.AttachedProperties) {
				item.RichText = new RichText("Attached Dependency Properties", new TextStyle(FontStyle.Italic));
				item.Images.Add(psiIconManager.GetImage(XamlDeclaredElementType.AttachedProperty));
			}
		}
		
		internal DpGeneratorField([NotNull] IField dpField, [NotNull] IType dpRegisteredType, bool isAttached)
			: base(dpField) {
			_dpRegisteredType = dpRegisteredType;
			_isAttached = isAttached;
		}
	}

}